package com.xtm.exercise.base.A08map.map01;

import cn.hutool.core.collection.CollUtil;
import com.google.common.collect.Maps;
import org.junit.Test;

import java.util.HashMap;
import java.util.Map;

/*
    java.util.Map<k,v>集合
    Map集合的特点:（是个接口，Map<String,Integer>）
        1.Map集合是一个双列集合,一个元素包含两个值(一个key,一个value)
        2.Map集合中的元素,key和value的数据类型可以相同,也可以不同
        3.Map集合中的元素,key是不允许重复的,value是可以重复的
        4.Map集合中的元素,key和value是一一对应

        如果key是对象，需要重写hashcode 和 equals 方法 ， 才能保证key唯一

    java.util.HashMap<k,v>集合 实现类 implements Map<k,v>接口
    HashMap集合的特点:  HashMap实现了Map接口
        1.HashMap集合底层是哈希表:查询的速度特别的快
          查询：是按照哈希算法查询的
          存储：
            JDK1.8之前:数组+单向链表
            JDK1.8之后:数组+单向链表|红黑树(链表的长度超过8):提高查询的速度
        2.hashMap集合是一个无序的集合,存储元素和取出元素的顺序有可能不一致

        HashMap底层实现原理：*****
         特点：
            数组：插入，删除慢，查询快
            链表：插入，删除快，查询慢
         存储位置：
            key.hashCode() % 16

         红黑树：
          为什么要用红黑树：
            容量不够，我们就只能把这个数据放到链表上，链表无线延长，这种hash冲突是十分严重的，而链表的特性是查询慢，而链表又无线延长，我们查询链表末端的数据，这样性能就很低了，所以JDK8 就用红黑树了！
            总结：解决链表过长查询效率过低的问题

            什么情况下用红黑树?
                前提条件  阈值 8
                HashMap 类下面有个这个：
                  static final int TREEIFY_THRESHOLD = 8;

   java.util.LinkedHashMap<k,v>集合 extends HashMap<k,v>集合
   LinkedHashMap的特点:
        1.LinkedHashMap集合底层是哈希表+链表(保证迭代的顺序)
        2.LinkedHashMap集合是一个有序的集合,存储元素和取出元素的顺序是一致的
 */
public class Demo01Map {

    @Test
    public void containsKey() {
        // 创建map  不用写泛型的方式
        HashMap<Object, Object> newHashMap = Maps.newHashMap();
        //创建Map集合对象
        Map<String,Integer> map = new HashMap<>();
        map.put("赵丽颖",168);
        map.put("杨颖",165);
        map.put("林志玲",178);

        // 非空判断
        if(CollUtil.isEmpty(map)){
            System.out.println("map为空");
        }
        if (map.isEmpty()){
            System.out.println("map为空");
        }else if(!map.isEmpty()){
            System.out.println("将注释放开，map不为空");
        }

        /*
            boolean containsKey(Object key) 判断集合中是否包含指定的键。
            包含返回true,不包含返回false
        */
        boolean b1 = map.containsKey("赵丽颖");
        System.out.println("b1:"+b1);//b1:true

        boolean b2 = map.containsKey("王颖");
        System.out.println("b2:"+b2);//b2:false

        System.out.println("#######################################################");
        /*
        public V get(Object key) 根据指定的键，在Map集合中获取对应的值。
            返回值:
                key存在,返回对应的value值
                key不存在,返回null
        */
        Integer v1 = map.get("杨颖");
        System.out.println("v1:"+v1);//v1:165

        Integer v2 = map.get("迪丽热巴");
        System.out.println("v2:"+v2);//v2:null
        System.out.println("#######################################################");
        /*
            public V remove(Object key): 把指定的键 所对应的键值对元素 在Map集合中删除，返回被删除元素的值。
                返回值:V
                    key存在,v返回被删除的值
                    key不存在,v返回null
         */
        Integer remover = map.remove("林志玲");
        System.out.println("v1:"+remover);//v1:178

        System.out.println(map);//{赵丽颖=168, 杨颖=165}
        System.out.println("#######################################################");
        /*
            public V put(K key, V value):  把指定的键与指定的值添加到Map集合中。
                返回值:v
                    存储键值对的时候,key不重复,返回值V是null
                    存储键值对的时候,key重复,会使用新的value替换map中重复的value,返回被替换的value值
         */
        //创建Map集合对象,多态
        Map<String,String> mapput = new HashMap<>();
        String v11 = mapput.put("李晨", "范冰冰1");
        System.out.println("v1:"+v11);//v1:null

        String v22 = mapput.put("李晨", "范冰冰2");
        System.out.println("v2:"+v22);//v2:范冰冰1

        System.out.println(mapput);//{李晨=范冰冰2}

        mapput.put("冷锋","龙小云");
        mapput.put("杨过","小龙女");
        mapput.put("尹志平","小龙女");
        System.out.println(mapput);//{杨过=小龙女, 尹志平=小龙女, 李晨=范冰冰2, 冷锋=龙小云}
    }

}
